
local Env = commonlib.inherit(nil);


function Env:ctor()
    self.m_env_instance = nil;           -- 所在环境实例
    self.m_env_instance_key = nil;       -- 所在环境实例键key对应的值
    self.m_data = nil;                   -- 环境数据
    self.m_instance = nil;               -- 实例
    self.m_metatable = nil;              -- 实例元素
    self.m_index_callback = nil;
    self.m_newindex_callback = nil;
end

function Env:Init(data, index_callback, newindex_callback, env_instance, env_instance_key)
    local __self__ = self;  -- __self__ ~= Env 是 Env 真实实例
    local metatable = {};
    local instance = setmetatable({}, metatable);

    data = type(data) == "table" and data or {};

    __self__.m_data = {};
    __self__.m_instance = instance;
    __self__.m_metatable = metatable;
    __self__.m_index_callback = index_callback;
    __self__.m_newindex_callback = newindex_callback;
    __self__.m_env_instance = env_instance;
    __self__.m_env_instance_key = env_instance_key;

    -- 读索引
    metatable.__index = function(_, key)
        -- 回去实例环境
        if (key == "__env__") then return __self__ end
        if (key == "__is_env__") then return true end

        -- 触发读回调
        local instance_env = __self__;
        local instacne_key = key;
        while (instance_env ~= nil and instacne_key ~= nil) do
            if (type(instance_env.m_index_callback) == "function") then
                (instance_env.m_index_callback)(instance_env.m_instance, instacne_key);
            end
            instacne_key = instance_env.m_env_instance_key;                                          -- 实例所在实例的Key值
            instance_env = instance_env.m_env_instance and instance_env.m_env_instance.__env__;      -- 实例所在实例的Env值
        end

        local value = __self__.m_data[key];
        if (value ~= nil) then return value end

        value = data[key];
        if (value ~= nil) then
            if (type(value) == "table" and value ~= _G and value ~= _ENV) then
                value = Env:new():Init(value, index_callback, newindex_callback, instance, key);
                __self__.m_data[key] = value;
            end
            return value;
        end

        return _G[key];
    end

    -- 写索引
    metatable.__newindex = function(_, key, val)
        -- 内置Key不支持更改
        if (key == "__env__" or key == "__is_env__") then return end

        -- 获取新旧值
        local old_val = instance[key];
        local new_val = val;

        -- 普通表转成Env值
        if (type(val) == "table" and not val.__is_env__) then
            new_val = Env:new():Init(val, index_callback, newindex_callback, instance, key);
        end

        -- 如果值相同则直接返回
        if (old_val == new_val) then return end

        -- 触发写回调
        if (type(__self__.m_newindex_callback) == "function") then
            (__self__.m_newindex_callback)(__self__.m_instance, key, new_val, old_val);
        end

        -- 赋值新值
        __self__.m_data[key] = new_val;
    end

    metatable.__len = function(_)
        return #(__self__.m_data);
    end

    metatable.__pairs = function(_)
        return pairs(__self__.m_data);
    end

    return instance;
end

-- local function index_callback(env, key)
--     print("index_callback", env, key);
-- end

-- local function newindex_callback(env, key, new_val, old_val)
--     print("newindex_callback", env, key, new_val, old_val);
-- end

-- local env = Env:new():Init(nil, index_callback, newindex_callback);
-- env.key = 1;
-- env.obj = {value = 2};
-- env.obj.value = 3;
-- local obj = env.obj;
-- obj.obj1 = 1;
-- obj.obj2 = 1;
-- table.insert(env, 1, {})
-- print()
return Env;